package com.gbas.gnet;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.Socket;

public class ClientThread extends Thread implements Serializable {
    /**
     * Escuchador de eventos del thread
     */
    NetListener nv = null;

    /**
     * Socket de conexion
     */
    Socket mSocket = null;

    /**
     * Objeto para enviar datos
     */
    ObjectOutputStream mOs = null;

    /**
     * Objetos para leer datos
     */
    ObjectInputStream mIs = null;

    /**
     * Duracion del ping (solo tareas servidor)
     */
    final int TIME_FOR_PING = 2000;

    /**
     * Detiene la tarea en curso
     */
    public boolean running = true;

    /**
     * Crea el thread
     *
     * @param nv   Interfaz que soporta todas las comunicaciones
     * @param so   Socket de comunicaciones abierto
     * @param name Nombre de la tarea (para tareas de depuracion).
     * @throws IOException problemas abriendo el socket
     */
    public ClientThread(NetListener nv, Socket so, String name)
            throws IOException {
        super(name);
        this.nv = nv;
        mSocket = so;
        mOs = new ObjectOutputStream(mSocket.getOutputStream());
        mIs = new ObjectInputStream(mSocket.getInputStream());
    }

    /**
     * Escucha a traves del socket. Lee objetos tipo NetObject.
     *
     * @see NetObject
     */
    public void run() {
        running = true;
        try {
            while (running) {
                NetObject nObj = (NetObject) mIs.readObject();
                //System.out.println("Leido Objeto "+nObj.toString());
                if (nv.isServer())
                    new MsgHandler(this, nObj, nv).start();
                else
                    nObj.action(this, nv);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        nv.netEventClose(this);
    }

    /**
     * Envia un objeto tipo NetObject a traves del socket
     *
     * @param nObj Objeto a enviar
     */
    public synchronized void send(NetObject nObj) {
        try {
            mOs.writeObject(nObj);
            mOs.reset();
        } catch (Exception e) {
            e.printStackTrace();
            nv.netEventClose(this);
        }
    }

    /**
     * Cierra y finaliza la tarea
     */
    public void close() {
        try {
            mOs.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            mIs.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            mSocket.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
